/*
 *	Copyright 2011 ja4cli
 *
 *	Licensed under the Apache License, Version 2.0 (the "License");
 *	you may not use this file except in compliance with the License.
 *	You may obtain a copy of the License at
 *
 *		http://www.apache.org/licenses/LICENSE-2.0
 *
 *	Unless required by applicable law or agreed to in writing, software
 *	distributed under the License is distributed on an "AS IS" BASIS,
 *	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *	See the License for the specific language governing permissions and
 *	limitations under the License.
 */
package org.skarby.ja4cli;

import java.util.Collections;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;

import org.skarby.ja4cli.conversion.ArgumentConverter;
import org.skarby.ja4cli.conversion.BooleanConverterFactory;
import org.skarby.ja4cli.conversion.CharacterConverterFactory;
import org.skarby.ja4cli.conversion.ConverterFactory;
import org.skarby.ja4cli.conversion.DoubleConverterFactory;
import org.skarby.ja4cli.conversion.FileConverterFactory;
import org.skarby.ja4cli.conversion.FloatConverterFactory;
import org.skarby.ja4cli.conversion.IntegerConverterFactory;
import org.skarby.ja4cli.conversion.LongConverterFactory;
import org.skarby.ja4cli.conversion.StringConverterFactory;
import org.skarby.ja4cli.conversion.URLConverterFactory;
import org.skarby.ja4cli.internal.Guard;

/**
 * Environment for parsing configurations.<p/>
 *  
 * @author askarby
 */
public class Environment implements LocaleAware {
	private Locale locale;
	private Set<ConverterFactory<? extends ArgumentConverter<?>, ?>> converters;
	private boolean debugMode;

	/**
	 * Constructs a default {@link Environment}.<p/>
	 * 
	 * All values hold by this Environment will be set to defaults, those being:
	 * <table>
	 * <tr><th>Field</th><th>Value</th></tr>
	 * <tr><td>Locale</td><td>English</td></tr>
	 * </table> 
	 */
	public Environment() {
		this(Locale.ENGLISH);
	}
	
	/**
	 * Constructs a new {@link Environment}.
	 * @param locale the locale to set upon the {@link Environment}
	 */
	public Environment(Locale locale) {
		setLocale(locale);

		// Register default converters
		converters = new HashSet<ConverterFactory<? extends ArgumentConverter<?>,?>>();
		converters.add(new BooleanConverterFactory());
		converters.add(new CharacterConverterFactory());
		converters.add(new DoubleConverterFactory());
		converters.add(new FileConverterFactory());
		converters.add(new FloatConverterFactory());
		converters.add(new IntegerConverterFactory());
		converters.add(new LongConverterFactory());
		converters.add(new StringConverterFactory());
		converters.add(new URLConverterFactory());
	}
	
	@Override
	public void setLocale(Locale locale) {
		Guard.isNull(locale, "Locale must be present, null is not an acceptable value");
		this.locale = locale;
	}

	@Override
	public Locale getLocale() {
		return locale;
	}
	
	public void setDebugMode(boolean debugMode) {
		this.debugMode = debugMode;
	}
	
	public boolean isDebugMode() {
		return debugMode;
	}
	
	public void addConverterFactory(ConverterFactory<? extends ArgumentConverter<?>, ?> factory) {
		converters.add(factory);
	}
	
	public Set<ConverterFactory<? extends ArgumentConverter<?>, ?>> getConverterFactories() {
		return Collections.unmodifiableSet(converters);
	}
	
	public ConverterFactory<? extends ArgumentConverter<?>, ?> getConverterFactory(Class<?> target) {
		for (ConverterFactory<? extends ArgumentConverter<?>, ?> factory : converters) {
			if (factory.supports(target)) {
				return factory;
			}
		}
		return null;
	}
}
